package com.sky.service.impl;

import com.alibaba.druid.sql.PagerUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.CategoryDTO;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Category;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.CategoryMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.SetmealService;
import com.sky.vo.DishItemVO;
import com.sky.vo.SetmealVO;
import com.sun.tools.classfile.ConstantPool;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.jni.Buffer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class SetmealServiceImpl implements SetmealService {
    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private SetmealDishMapper setmealDishMapper;

    /**
     * 分页查询
     *
     * @param setmealPageQueryDTO
     * @return
     */
    @Override
    public PageResult page(SetmealPageQueryDTO setmealPageQueryDTO) {
        //1.使用PageHelper分页插件，设置分页参数
        PageHelper.startPage(setmealPageQueryDTO.getPage(), setmealPageQueryDTO.getPageSize());

        //2.调用Mapper层进行数据查询并强转返回类型为Page
        Page<SetmealVO> setmealVOPage = setmealMapper.pageQuerySetmeal(setmealPageQueryDTO);
        //2.1 补全返回值参数，根据category_id查询分类表获取分类名称

        //3.封装PageResult对象并返回
        return new PageResult(setmealVOPage.getTotal(), setmealVOPage.getResult());
    }

    /**
     * 根据id查询套餐
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public SetmealVO getSetmealById(Long id) {
        //1.新建一个SetmealDTO对象
        SetmealVO setmealVO = new SetmealVO();

        //1.查询套餐信息
        Setmeal setmeal = setmealMapper.getSetmealById(id);

        //2.查询套餐菜品信息
        List<SetmealDish> setmealDishes = setmealDishMapper.getSetmealDishesById(id);

        //3.合并
        BeanUtils.copyProperties(setmeal, setmealVO);
        setmealVO.setSetmealDishes(setmealDishes);

        return setmealVO;
    }

    /**
     * 套餐起售、停售
     *
     * @param status
     * @param id
     */
    @Override
    public void status(Integer status, Long id) {
        setmealMapper.alterStatus(status, id);
    }

    /**
     * 新增套餐
     *
     * @param setmealDTO
     */
    @Override
    @Transactional
    public void insertSetmeal(SetmealDTO setmealDTO) {
        //1.创建Setmeal、SetmealDish对象，并拷贝Setmeal属性
        Setmeal setmeal = new Setmeal();

        BeanUtils.copyProperties(setmealDTO, setmeal);

        //2. 新增套餐
        setmealMapper.insertSetmeal(setmeal);

        //3.新增套餐菜品关系
        //获取生成的套餐id   通过sql中的useGeneratedKeys="true" keyProperty="id"获取插入后生成的主键值
        //套餐菜品关系表的setmealId页面不能传递，它是向套餐表插入数据之后生成的主键值，也就是套餐菜品关系表的逻辑外键setmealId
        Long setmealId = setmeal.getId();

        //获取页面传来的套餐和菜品关系表数据
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();

        //遍历关系表数据，为关系表中的每一条数据(每一个对象)的setmealId赋值，
        //   这个地方不需要像之前写新增菜品时多写个if判断，因为之前的口味数据是非必须的，
        //   这个地方要求套餐必须包含菜品是必须的，所以不需要if判断，不存在套餐不包含菜品得情况
        setmealDishes.forEach(setmealDish -> {
            //将Setmeal套餐类的id属性赋值给SetmealDish套餐关系类的setmealId
            //套餐表的id保存在套餐关系表充当外键为setmealId
            setmealDish.setSetmealId(setmealId);
        });

        //保存套餐和菜品的关联关系  动态sql批量插入
        setmealDishMapper.insertSetmealDish(setmealDishes);
    }

    /**
     * 批量删除套餐
     *
     * @param ids
     */
    @Override
    @Transactional
    public void delete(List<Long> ids) {
        //1.删除套餐
        //1.1 先根据id查询套餐，判断套餐是否起售，起售中的套餐不能删除
        ids.forEach(id -> {
            Setmeal setmeal = setmealMapper.getSetmealById(id);
            Integer status = setmeal.getStatus();
            if (status.equals(StatusConstant.ENABLE)) {
                throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
            }
        });

        setmealMapper.deleteByIds(ids);
        //2.删除套餐菜品
        setmealDishMapper.deleteBatchBySetmealId(ids);

    }

    /**
     * 修改套餐
     *
     * @param setmealDTO
     */
    @Override
    @Transactional //同时操作两张及以上的表
    public void update(SetmealDTO setmealDTO) {
        //1.创建套餐对象
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);
        //1.修改套餐
        setmealMapper.update(setmeal);

        //2.修改套餐菜品信息
        //2.1获取到setmealId信息
        Long setmealId = setmealDTO.getId();
        //2.2创建ArrayList对象，并存入setmealId
        ArrayList<Long> setmealIds = new ArrayList<>();
        setmealIds.add(setmealId);

        //2.2根据id删除套餐菜品信息
        setmealDishMapper.deleteBatchBySetmealId(setmealIds);

        //2.3菜品信息
        //获取菜品口味信息
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        //判断是否为空，并遍历设置SetmealId
        if (!setmealDishes.isEmpty()) {
            setmealDishes.forEach(setmealDish -> {
                setmealDish.setSetmealId(setmeal.getId());
            });

            //2.4插入套餐菜品信息
            setmealDishMapper.insertSetmealDish(setmealDishes);
        }
    }

    /**
     * 根据分类id查询套餐
     * @param setmeal
     * @return
     */
    @Override
    public List<Setmeal> list(Setmeal setmeal) {
        List<Setmeal> setmeals = setmealMapper.list(setmeal);

        return setmeals;
    }

    /**
     * 根据套餐id查询包含的菜品
     * @param id
     * @return
     */
    @Override
    public List<DishItemVO> getDishItemById(Long id) {
        //先查询setmeal_dish获取菜品名称和份数，以及dish_id
        //再根据dish_id查询菜品表的菜品图片和菜品描述
        return setmealMapper.getDishItemById(id);
    }
}
